﻿using IPC.WinForm.BaseForm;
using IPC.WinForm.ControlExtend;
using IPC.ListConnect.ListProprety;
using IPC.ListConnect.Profinet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrackBar;
using System.Security.Authentication;
using System.Xml.Serialization;
using System.Xml;
using Newtonsoft.Json;
using IPC.WinForm.Bussiness;
using IPC.ListConnect.Connect;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json.Linq;
using IPC.LogCommon.log4net;
using System.Xml.Linq;
using MongoDB.Bson;
using IPC.WinForm.ViewModel;
using IPC.ListConnect;

namespace IPC.WinForm
{
    public partial class FrmMain : Form
    {
        private ChannelType _channelType = ChannelType.None;

        private string _channelName = string.Empty;
        private string _channelGuid = string.Empty;
        private EquipChannel _equipChannel;

        WebApplication app;

        #region 初始化
        public FrmMain()
        {
            InitializeComponent();

            LogClass.Instance.Info("初始化");
            Task.Run(() => StartWebApi());
            InitConfig();
            notifyIcon1.Visible = true;
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {
            treeView1.ExpandAll();
        }

        /// <summary>
        /// 初始化之前的配置  通道 设备 组 标签
        /// </summary>
        private Task<bool> InitConfig()
        {
            try
            {
                List<DbMapper.Channel> channels = DbBussiness.Instance.GetChannels();
                foreach (var item in channels)
                {
                    EquipChannel equipChannel = new EquipChannel()
                    {
                        Guid = item.Guid,
                        ChannelName = item.ChannelName,
                        ChannelType = item.ChannelType
                    };
                    TreeNodeExtend treeNodeChannel = AddChannel(item.ChannelName, item.ChannelType, item.Guid);
                    this.treeView1.Nodes[0].Nodes[0].Nodes.Add(treeNodeChannel);
                    EquipChannels.Instance.EquipChannelList.Add(equipChannel);
                    List<DbMapper.Equip> equips = DbBussiness.Instance.GetEquipsByChannel(item.Guid);
                    foreach (var itemEquip in equips)
                    {
                        Equip equip = new Equip(itemEquip.Guid, itemEquip.Ip, itemEquip.Port, itemEquip.Slot, itemEquip.Rack, itemEquip.Type,
                            itemEquip.ChannelType, itemEquip.ChannelName, itemEquip.Name, itemEquip.EquipFullName);
                        TreeNodeExtend treeNodeEquip = AddEquip(equip);
                        treeNodeChannel.Nodes.Add(treeNodeEquip);
                        equipChannel.Equips.Add(itemEquip.EquipFullName, equip);
                        List<DbMapper.Group> groups = DbBussiness.Instance.GetGroupsByEquip(itemEquip.EquipFullName);
                        foreach (var itemGroup in groups)
                        {
                            Group group = new Group()
                            {
                                Guid = itemGroup.Guid,
                                Name = itemGroup.Name,
                                GroupFullName = itemGroup.GroupFullName
                            };
                            TreeNodeExtend treeNodeGroup = AddGroup(group);
                            treeNodeEquip.Nodes.Add(treeNodeGroup);
                            equip.Groups.Add(itemGroup.GroupFullName, group);
                            List<DbMapper.Tag> tags = DbBussiness.Instance.GetTagsByGroup(group.GroupFullName);
                            foreach (var itemTag in tags)
                            {
                                IPC.ListConnect.Profinet.Tag tag = new Tag(itemTag.Guid, itemTag.Name, itemTag.Address, itemTag.Remark, (DataType)Enum.Parse(typeof(DataType), itemTag.DataType),
                                    (ReadWrite)Enum.Parse(typeof(ReadWrite), itemTag.ReadWrite), itemTag.Frequency, itemTag.Zoom, itemTag.FullName);

                                group.Tags.Add(itemTag.FullName, tag);
                            }
                        }

                        List<DbMapper.Tag> equipTags = DbBussiness.Instance.GetTagsByEquip(equip.EquipFullName);
                        foreach (var itemTag in equipTags)
                        {
                            IPC.ListConnect.Profinet.Tag tag = new Tag(itemTag.Guid, itemTag.Name, itemTag.Address, itemTag.Remark, (DataType)Enum.Parse(typeof(DataType), itemTag.DataType),
                              (ReadWrite)Enum.Parse(typeof(ReadWrite), itemTag.ReadWrite), itemTag.Frequency, itemTag.Zoom, itemTag.FullName);
                            equip.Tags.Add(itemTag.FullName, tag);
                        }
                    }
                }
                this.treeView1.ExpandAll();
                return Task.FromResult(true);
            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"系统初始化失败 {ex.Message}");
                this.richTextBox1.AppendText($"{DateTime.Now} 系统初始化失败 {ex.Message} \n");
                return Task.FromResult(false);
            }
        }
        #endregion

        #region 新建通道
        /// <summary>
        /// 新建通道
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 新建通道ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                FrmNewChannel frmNewChannel = new FrmNewChannel();
                if (frmNewChannel.ShowDialog() == DialogResult.OK)
                {
                    string channelName = frmNewChannel.ChannelName;
                    string channelType = frmNewChannel.ChannelType;
                    string guid = frmNewChannel.ChannelGuid;
                    this.treeView1.SelectedNode.Nodes.Add(AddChannel(channelName, channelType, guid));
                    this.treeView1.SelectedNode.ExpandAll();

                    DbBussiness.Instance.AddChannel(channelName, channelType, guid);
                    ConnectList.Instance = null;
                    LogClass.Instance.Info($"添加通道{channelName},{channelType}");
                }
            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"添加通道失败 {ex.Message}");
                this.richTextBox1.AppendText($"{DateTime.Now} 新建通道失败 {ex.Message} \n");
            }
        }

        private TreeNodeExtend AddChannel(string channelName, string channelType, string? guid)
        {
            TreeNodeExtend treeNode = new TreeNodeExtend(channelName);
            treeNode.ImageKey = "Icons_16x16_Search.png";
            treeNode.Name = guid;
            treeNode.SelectedImageKey = "Icons_16x16_Search.png";
            treeNode.ContextMenuStrip = this.contextMenuStrip2;
            treeNode.NodeType = TreeNodeType.Channel;
            treeNode.FullName = guid;
            switch (channelType)
            {
                case "Siemens":
                    treeNode.ChannelType = ChannelType.Siemens; break;
                case "AllenBradley":
                    treeNode.ChannelType = ChannelType.AllenBradley; break;
                case "Virtual":
                    treeNode.ChannelType = ChannelType.Virtual; break;
                default:
                    treeNode.ChannelType = ChannelType.None; break;
            }


            this.richTextBox1.AppendText($"{DateTime.Now} 新建通道 {channelName} \n");

            return treeNode;
        }
        #endregion

        #region 新建设备
        /// <summary>
        /// 新建设备
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 新建设备ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                FrmNewEquip frmNewEquip = new FrmNewEquip(_channelType, _channelName, _channelGuid);
                if (frmNewEquip.ShowDialog() == DialogResult.OK)
                {
                    Equip equip = new Equip(frmNewEquip.Guid, frmNewEquip.IP, frmNewEquip.Port, frmNewEquip.Slot, frmNewEquip.Rack, frmNewEquip.Type, _channelType.ToString(), _channelName,
                        frmNewEquip.Name, frmNewEquip.FullName);
                    #region 判断设备是否已存在
                    foreach (var item in _equipChannel.Equips.Values)
                    {
                        if (frmNewEquip.Name == item.Name)
                        {
                            MessageBox.Show("设备已存在");
                            return;
                        }
                    }
                    #endregion
                    _equipChannel.Equips.Add(equip.EquipFullName, equip);
                    this.treeView1.SelectedNode.Nodes.Add(AddEquip(equip));
                    this.treeView1.ExpandAll();
                    DbBussiness.Instance.AddEquip(equip.Ip, equip.Port, equip.Slot, equip.Rack, equip.Type, equip.Name, equip.EquipFullName, _channelGuid, equip.Guid, equip.ChannelType);
                    ConnectList.Instance = null;
                    LogClass.Instance.Info($"添加设备ip{equip.Ip},端口{equip.Port},槽口号{equip.Slot},机架号{equip.Rack},类型{equip.Type},名称{equip.Name},所属通道{_channelName}");
                }
            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"新建设备失败,失败原因{ex.Message}");
                this.richTextBox1.AppendText($"{DateTime.Now} 新建设备失败 {ex.Message} \n");
            }
        }

        /// <summary>
        /// 添加设备
        /// </summary>
        /// <param name="equip"></param>
        private TreeNodeExtend AddEquip(Equip equip)
        {
            #region 添加节点
            TreeNodeExtend treeNode = new TreeNodeExtend(equip.Name);
            treeNode.ImageKey = "Icons_16x16_ToolBox.png";
            treeNode.SelectedImageKey = "Icons_16x16_ToolBox.png";
            treeNode.ContextMenuStrip = this.contextMenuStrip3;
            treeNode.NodeType = TreeNodeType.Equip;
            treeNode.Name = equip.EquipFullName;
            treeNode.FullName = equip.EquipFullName;
            switch (equip.Type)
            {
                case "AB5000": treeNode.EquipType = EquipType.AB5000; break;
                case "AB500": treeNode.EquipType = EquipType.AB500; break;
                case "S7_200": treeNode.EquipType = EquipType.S7_200; break;
                case "S7_200Smart": treeNode.EquipType = EquipType.S7_200Smart; break;
                case "S7_300": treeNode.EquipType = EquipType.S7_300; break;
                case "S7_400": treeNode.EquipType = EquipType.S7_400; break;
                case "S7_1200": treeNode.EquipType = EquipType.S7_1200; break;
                case "S7_1500": treeNode.EquipType = EquipType.S7_1500; break;
                default: treeNode.EquipType = EquipType.None; break;
            }

            //
            #endregion

            this.richTextBox1.AppendText($"{DateTime.Now} 新建设备 {equip.Name} \n");
            return treeNode;
        }
        #endregion

        #region 双击显示
        /// <summary>
        /// 双击显示
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.Visible = true;
            this.Activate();
            //notifyIcon1.Visible = false;
        }
        #endregion

        #region 关闭到托盘
        /// <summary>
        /// 关闭到托盘
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            this.Visible = false;
            //this.Close();
            //notifyIcon1.Visible = true;
        }
        #endregion

        #region 退出
        /// <summary>
        /// 退出
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 退出XToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LogClass.Instance.Info("退出客户端");
            this.Dispose();
            this.Close();
        }
        #endregion

        #region 删除通道
        /// <summary>
        /// 删除通道
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 删除ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                string name = this.richTextBox1.Text;
                string guid = this.treeView1.SelectedNode.Name;
                foreach (var item in EquipChannels.Instance.EquipChannelList)
                {
                    if (item.Guid == guid)
                    {
                        foreach (var itemEquip in item.Equips.Values)
                        {
                            itemEquip.WillClose();
                        }
                        EquipChannels.Instance.EquipChannelList.Remove(item);
                        break;
                    }
                }
                this.treeView1.SelectedNode.Remove();

                this.richTextBox1.AppendText($"{DateTime.Now} 删除通道 {name} \n");

                DbBussiness.Instance.RemoveChannel(guid);
                ConnectList.Instance = null;
                LogClass.Instance.Info($"删除通道{name}");

            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"删除通道失败{ex.Message}");
                this.richTextBox1.AppendText($"{DateTime.Now} 删除通道失败 {ex.Message} \n");
            }
        }
        #endregion

        #region 选中节点
        /// <summary>
        /// 选中节点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {

            if (this.treeView1.SelectedNode is TreeNodeExtend)
            {
                TreeNodeExtend treeNode = this.treeView1.SelectedNode as TreeNodeExtend;

                foreach (var item in EquipChannels.Instance.EquipChannelList)
                {
                    string channelGuid = this.treeView1.SelectedNode.Name;
                    if (item.Guid == channelGuid)
                    {
                        _channelType = treeNode.ChannelType;
                        _channelName = treeNode.Text;
                        _channelGuid = channelGuid;
                        _equipChannel = item;
                        break;
                    }
                }

                switch (treeNode.NodeType)
                {
                    case TreeNodeType.Channel:  //如果选中的是通道
                        this.dataGridView1.Visible = false;
                        break;
                    case TreeNodeType.Equip: //如果选中的是设备
                        this.dataGridView1.Visible = true;
                        RefreshTags(treeNode);
                        break;
                    case TreeNodeType.Group: //如果选中的是组
                        this.dataGridView1.Visible = true;
                        RefreshTags(treeNode);
                        break;
                    case TreeNodeType.Tag: //如果选中的是标签
                        break;
                }

            }
            else
            {
                this.dataGridView1.Visible = false;
            }
        }
        #endregion

        #region 新建组
        private void 新建组ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                FrmNewGroup frmNewGroup = new FrmNewGroup();
                string equipFullName = (this.treeView1.SelectedNode as TreeNodeExtend).FullName;
                if (frmNewGroup.ShowDialog() == DialogResult.OK)
                {
                    Group group = new Group()
                    {
                        Guid = frmNewGroup.GroupGuid,
                        Name = frmNewGroup.GroupName,
                        GroupFullName = equipFullName + "." + frmNewGroup.GroupGuid,
                    };
                    BaseClass baseClass = GetNewNode(this.treeView1.SelectedNode);
                    if (baseClass is Equip)
                    {
                        Equip equip = baseClass as Equip;
                        bool b = false;
                        foreach (var item in equip.Groups.Values)
                        {
                            if (group.Name == item.Name)
                            {
                                b = true;
                                break;
                            }
                        }

                        if (!b)
                        {
                            equip.Groups.Add(group.GroupFullName, group);
                        }
                        else
                        {
                            MessageBox.Show("组已存在");
                            this.richTextBox1.AppendText($"{DateTime.Now} 新建组失败 {group.Name} 已存在 \n");
                            return;
                        }
                    }
                    else
                    {
                        return;
                    }

                    this.treeView1.SelectedNode.Nodes.Add(AddGroup(group));
                    this.treeView1.ExpandAll();

                    DbBussiness.Instance.AddGroup(group.Name, group.GroupFullName, equipFullName, group.Guid);
                    ConnectList.Instance = null;
                    LogClass.Instance.Info($"添加组，名称{group.Name}，所属设备{equipFullName}");
                }
            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"添加组失败{ex.Message}");
                this.richTextBox1.AppendText($"{DateTime.Now} 新建组失败 {ex.Message} \n");
            }
        }

        private TreeNodeExtend AddGroup(Group group)
        {
            TreeNodeExtend treeNode = new TreeNodeExtend(group.Name);
            treeNode.ImageKey = "Icons_16x16_Open.png";
            treeNode.SelectedImageKey = "Icons_16x16_Open.png";
            treeNode.NodeType = TreeNodeType.Group;
            treeNode.ContextMenuStrip = this.contextMenuStrip4;
            treeNode.Name = group.GroupFullName;
            treeNode.FullName = group.GroupFullName;


            this.richTextBox1.AppendText($"{DateTime.Now} 新建组 {group.Name} \n");
            return treeNode;
        }

        #endregion

        #region 删除组
        private void 删除组ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                string groupName = this.treeView1.SelectedNode.Text;
                string groupFullName = this.treeView1.SelectedNode.Name;
                string equipFullName = (this.treeView1.SelectedNode.Parent as TreeNodeExtend).FullName;
                string channelGuid = groupFullName.Split('.')[0];
                string equipGuid = groupFullName.Split('.')[1];
                string groupGuid = groupFullName.Split(".")[2];
                foreach (var item in EquipChannels.Instance.EquipChannelList)
                {
                    if (item.Guid == channelGuid)
                    {
                        item.Equips[equipFullName].Groups.Remove(groupFullName);
                        break;
                    }
                }
                this.richTextBox1.AppendText($"{DateTime.Now} 删除组 {groupName} \n");
                this.treeView1.SelectedNode.Remove();

                DbBussiness.Instance.RemoveGroup(groupFullName);
                LogClass.Instance.Info($"删除组，名称{groupFullName}");
            }
            catch (Exception ex)
            {
                this.richTextBox1.AppendText($"{DateTime.Now} 删除组失败 {ex.Message} \n");
                LogClass.Instance.Error($"删除组失败{ex.Message}");
            }
        }
        #endregion

        #region 删除标签
        private void 删除标签ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.dataGridView1.SelectedRows.Count <= 0)
                    return;
                DataGridViewSelectedRowCollection dataGridViewSelectedRowCollection = this.dataGridView1.SelectedRows;
                foreach (DataGridViewRow item in dataGridViewSelectedRowCollection)
                {
                    DataTable dataTable = this.dataGridView1.DataSource as DataTable;
                    string dataName = item.Cells["DataName"].Value.ToString();

                    #region 将集合中的标签删除
                    string tagFullName = item.Cells["FullName"].Value.ToString();
                    string[] tagsName = tagFullName.Split('.');
                    if (tagsName.Length == 3) //在设备下的标签
                    {
                        string equipFullName = tagsName[0] + "." + tagsName[1];
                        foreach (var itemChannel in EquipChannels.Instance.EquipChannelList)
                        {
                            if (itemChannel.Guid == tagsName[0])
                            {
                                itemChannel.Equips[equipFullName].Tags[tagFullName].WillClose();
                                itemChannel.Equips[equipFullName].Tags.Remove(tagFullName);
                                break;
                            }
                        }
                    }
                    else if (tagsName.Length == 4) //在组下的标签
                    {
                        string equipFullName = tagsName[0] + "." + tagsName[1];
                        string groupFullName = tagsName[0] + "." + tagsName[1] + "." + tagsName[2];
                        foreach (var itemChannel in EquipChannels.Instance.EquipChannelList)
                        {
                            if (itemChannel.Guid == tagsName[0])
                            {
                                itemChannel.Equips[equipFullName].Groups[groupFullName].Tags[tagFullName].WillClose();
                                itemChannel.Equips[equipFullName].Groups[groupFullName].Tags.Remove(tagFullName);
                                break;
                            }
                        }
                    }
                    #endregion

                    foreach (DataRow item2 in dataTable.Rows)
                    {
                        if (item2["DataName"].ToString() == dataName)
                        {
                            dataTable.Rows.Remove(item2);
                            break;
                        }
                        this.richTextBox1.AppendText($"{DateTime.Now} 删除标签 {item2["DataName"].ToString()} \n");
                    }

                    DbBussiness.Instance.RemoveTag(tagFullName);
                    LogClass.Instance.Info($"删除标签，名称{tagFullName}");
                }
            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"删除标签失败{ex.Message}");
                this.richTextBox1.AppendText($"{DateTime.Now} 删除标签失败 {ex.Message} \n");
            }
        }
        #endregion

        #region 新建标签
        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {
            try
            {
                string equipFullName = "";
                string groupFullName = "";
                FrmNewTag frmNewTag = new FrmNewTag();
                if (frmNewTag.ShowDialog() == DialogResult.OK)
                {
                    IPC.ListConnect.Profinet.Tag tag = new Tag(frmNewTag.TagGuid, frmNewTag.TagName, frmNewTag.TagAddress, frmNewTag.TagRemark, frmNewTag.TagDataType,
                       frmNewTag.ReadWrite, frmNewTag.Frequency, frmNewTag.Zoom, this.treeView1.SelectedNode.Name + "." + frmNewTag.TagGuid);

                    #region 添加标签
                    BaseClass baseClass = GetNewNode(this.treeView1.SelectedNode);
                    if (baseClass is Equip)
                    {
                        Equip equip = (Equip)baseClass;
                        foreach (var item in equip.Tags.Values)
                        {
                            if (item.Name == tag.Name)
                            {
                                MessageBox.Show("标签已存在");
                                return;
                            }
                        }
                        foreach (var item in equip.Tags.Values)
                        {
                            if (item.Address == tag.Address)
                            {
                                MessageBox.Show("标签已存在");
                                return;
                            }
                        }

                        equip.Tags.Add(tag.FullName, tag);
                        equipFullName = this.treeView1.SelectedNode.Name;
                    }

                    else if (baseClass is Group)
                    {
                        Group group = (Group)baseClass;
                        foreach (var item in group.Tags.Values)
                        {
                            if (item.Name == tag.Name)
                            {
                                MessageBox.Show("标签已存在");
                                return;
                            }
                        }

                        foreach (var item in group.Tags.Values)
                        {
                            if (item.Address == tag.Address)
                            {
                                MessageBox.Show("标签已存在");
                                return;
                            }
                        }
                        groupFullName = this.treeView1.SelectedNode.Name;
                        group.Tags.Add(tag.FullName, tag);
                    }

                    else
                    {
                        MessageBox.Show("当前节点不可添加标签");
                        return;
                    }
                    #endregion

                    this.richTextBox1.AppendText($"{DateTime.Now} 新建标签成功 {tag.Name} \n");

                    RefreshTags(this.treeView1.SelectedNode);

                    DbBussiness.Instance.AddTag(tag.Name, tag.Address, tag.DataType.ToString(), tag.Frequency, tag.Zoom, tag.Remark, tag.Value, tag.ReadWrite.ToString(), tag.FullName, groupFullName, equipFullName, tag.Guid);
                    LogClass.Instance.Info($"新建标签，名称{tag.Name},地址{tag.Address},数据类型{tag.DataType.ToString()},备注{tag.Remark},读写{tag.ReadWrite.ToString()},全名{tag.FullName}");
                }
            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"删除标签失败{ex.Message}");
                this.richTextBox1.AppendText($"{DateTime.Now} 新建标签失败 {ex.Message} \n");
            }
        }
        #endregion

        #region 刷新当前选中节点下的标签
        public void RefreshTags(TreeNode treeNode)
        {
            BaseClass baseClass = GetNewNode(treeNode);
            if (baseClass is Equip)
            {
                Equip equip = (Equip)baseClass;
                DataTable dataTable = new DataTable();
                dataTable.Columns.Add("DataName", typeof(string));
                dataTable.Columns.Add("Address", typeof(string));
                dataTable.Columns.Add("DataType", typeof(string));
                dataTable.Columns.Add("ReadWrite", typeof(string));
                dataTable.Columns.Add("Frequency", typeof(string));
                dataTable.Columns.Add("Zoom", typeof(string));
                dataTable.Columns.Add("Remark", typeof(string));
                dataTable.Columns.Add("FullName", typeof(string));
                foreach (var item in equip.Tags.Values)
                {
                    DataRow dataRow = dataTable.NewRow();
                    dataRow["DataName"] = item.Name;
                    dataRow["Address"] = item.Address;
                    dataRow["DataType"] = item.DataType;
                    dataRow["ReadWrite"] = item.ReadWrite;
                    dataRow["Frequency"] = item.Frequency;
                    dataRow["Zoom"] = item.Zoom;
                    dataRow["Remark"] = item.Remark;
                    dataRow["FullName"] = item.FullName;
                    dataTable.Rows.Add(dataRow);
                }

                //this.dataGridView1.DataSource = null;
                this.dataGridView1.DataSource = dataTable;
            }
            else if (baseClass is Group)
            {
                Group group = (Group)baseClass;
                DataTable dataTable = new DataTable();
                dataTable.Columns.Add("DataName", typeof(string));
                dataTable.Columns.Add("Address", typeof(string));
                dataTable.Columns.Add("DataType", typeof(string));
                dataTable.Columns.Add("ReadWrite", typeof(string));
                dataTable.Columns.Add("Frequency", typeof(string));
                dataTable.Columns.Add("Zoom", typeof(string));
                dataTable.Columns.Add("Remark", typeof(string));
                dataTable.Columns.Add("FullName", typeof(string));
                foreach (var item in group.Tags.Values)
                {
                    DataRow dataRow = dataTable.NewRow();
                    dataRow["DataName"] = item.Name;
                    dataRow["Address"] = item.Address;
                    dataRow["DataType"] = item.DataType;
                    dataRow["ReadWrite"] = item.ReadWrite;
                    dataRow["Frequency"] = item.Frequency;
                    dataRow["Zoom"] = item.Zoom;
                    dataRow["Remark"] = item.Remark;
                    dataRow["FullName"] = item.FullName;
                    dataTable.Rows.Add(dataRow);
                }

                //this.dataGridView1.DataSource = null;
                this.dataGridView1.DataSource = dataTable;
            }
            this.dataGridView1.ClearSelection();
        }
        #endregion

        #region 返回当前选择的节点
        private BaseClass GetNewNode(TreeNode treeNode)
        {

            if (treeNode is TreeNodeExtend)
            {
                TreeNodeExtend treeNodeExtend = treeNode as TreeNodeExtend;

                #region 通道
                if (treeNodeExtend.NodeType == TreeNodeType.Channel)
                {
                    foreach (EquipChannel node in EquipChannels.Instance.EquipChannelList)
                    {
                        if (node.Guid == treeNode.Name)
                        {
                            return node;
                        }
                    }
                }
                #endregion

                #region 设备
                else if (treeNodeExtend.NodeType == TreeNodeType.Equip)
                {
                    string channelName = treeNode.Parent.Text;
                    string equipName = treeNode.Text;
                    string channelGuid = treeNode.Parent.Name;
                    foreach (var item in EquipChannels.Instance.EquipChannelList)
                    {
                        if (item.Guid == channelGuid)
                        {
                            return item.Equips[treeNodeExtend.FullName];
                        }
                    }
                }
                #endregion

                #region 组
                else if (treeNodeExtend.NodeType == TreeNodeType.Group)
                {
                    string equipFullName = (treeNodeExtend.Parent as TreeNodeExtend).FullName;
                    string groupFullName = treeNodeExtend.FullName;
                    string channelGuid = groupFullName.Split('.')[0];
                    foreach (var item in EquipChannels.Instance.EquipChannelList)
                    {
                        if (item.Guid == channelGuid)
                        {
                            return item.Equips[equipFullName].Groups[groupFullName];
                        }
                    }
                }
                #endregion
            }

            return new BaseClass();
        }
        #endregion

        #region 删除设备
        private void 删除设备ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                string equipFullName = this.treeView1.SelectedNode.Name;
                string channelName = equipFullName.Split('.')[0];
                string equipName = equipFullName.Split('.')[1];
                foreach (var item in EquipChannels.Instance.EquipChannelList)
                {
                    if (item.Guid == channelName)
                    {
                        item.Equips[equipFullName].WillClose();
                        item.Equips.Remove(equipFullName);
                        break;
                    }
                }
                this.richTextBox1.AppendText($"{DateTime.Now} 删除设备 {equipName} \n");
                this.treeView1.SelectedNode.Remove();

                DbBussiness.Instance.RemoveEquip(equipFullName);
                ConnectList.Instance = null;
                LogClass.Instance.Info($"删除设备{equipFullName}");
            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"删除设备失败{ex.Message}");
                this.richTextBox1.AppendText($"{DateTime.Now} 删除设备失败 {ex.Message} \n");
            }
        }
        #endregion

        #region 运行
        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            FrmRealTimeValue.Instance.ShowInstance();
            //FrmRealTimeValue frmRealTimeValue = new FrmRealTimeValue();
            //frmRealTimeValue.Show();
        }
        #endregion

        #region 退出
        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LogClass.Instance.Error($"退出客户端");
            this.Dispose();
            this.Close();
        }
        #endregion

        #region 解决鼠标右键点击不算选中问题
        private void treeView1_MouseDown(object sender, MouseEventArgs e)
        {
            this.treeView1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.treeView_MouseDown);
        }

        private void treeView_MouseDown(object sender, MouseEventArgs e)
        {
            TreeView tv = sender as TreeView;
            if (tv == null)
            {
                return;
            }
            if (e.Button == MouseButtons.Right)
            {
                TreeNode selectedNode = tv.GetNodeAt(e.Location);
                tv.SelectedNode = selectedNode;
            }
        }
        #endregion

        #region 寻找节点
        public TreeNode SelectNode(string nodeName)
        {
            if (String.IsNullOrWhiteSpace(nodeName)) //根节点
            {
                return this.treeView1.Nodes[0].Nodes[0];
            }
            else
            {
                foreach (TreeNode item in this.treeView1.Nodes[0].Nodes[0].Nodes)
                {
                    if (item.Name == nodeName)
                    {
                        return item;
                    }

                    foreach (TreeNode itemEquip in item.Nodes)
                    {
                        if (itemEquip.Name == nodeName)
                        {
                            return itemEquip;
                        }

                        foreach (TreeNode itemGroup in itemEquip.Nodes)
                        {
                            if (itemGroup.Name == nodeName)
                            {
                                return itemGroup;
                            }
                        }
                    }
                }
                return null;
            }
        }
        #endregion

        #region 编辑标签
        private void toolStripMenuItem2_Click_1(object sender, EventArgs e)
        {
            if (this.dataGridView1.SelectedRows.Count <= 0) return;



            string tagFullName = this.dataGridView1.SelectedRows[0].Cells["FullName"].Value.ToString();
            string[] names = tagFullName.Split('.');
            string groupGuid = "";
            string equipGuid = names[0] + "." + names[1];
            string channelName = names[0];
            if (names.Count() > 3)
            {
                groupGuid = names[0] + "." + names[1] + "." + names[2];
            }


            Tag tag = null;
            foreach (var item in EquipChannels.Instance.EquipChannelList)
            {
                if (item.Guid == channelName)
                {
                    if (groupGuid != "")
                    {
                        tag = item.Equips[equipGuid].Groups[groupGuid].Tags[tagFullName];
                    }
                    else
                    {
                        tag = item.Equips[equipGuid].Tags[tagFullName];
                    }
                    break;
                }
            }

            if (tag != null)
            {
                FrmNewTag frmNewTag = new FrmNewTag(tag.Name, tag.Remark, tag.Address, tag.DataType, tag.ReadWrite, tag.Frequency, tag.Zoom, tag.Guid);
                if (frmNewTag.ShowDialog() == DialogResult.OK)
                {
                    #region 判断标签是否已存在
                    foreach (var item in EquipChannels.Instance.EquipChannelList)
                    {
                        if (item.Guid == channelName)
                        {
                            if (groupGuid != "")
                            {
                                foreach (var item2 in item.Equips[equipGuid].Groups[groupGuid].Tags.Values)
                                {
                                    if (item2.Name == frmNewTag.TagName && item2.FullName != tagFullName)
                                    {
                                        MessageBox.Show("标签已存在");
                                        return;
                                    }
                                }
                            }
                            else
                            {
                                foreach (var item2 in item.Equips[equipGuid].Tags.Values)
                                {
                                    if (item2.Name == frmNewTag.TagName && item2.FullName != tagFullName)
                                    {
                                        MessageBox.Show("标签已存在");
                                        return;
                                    }
                                }
                            }
                            break;
                        }
                    }
                    #endregion

                    foreach (var item in EquipChannels.Instance.EquipChannelList)
                    {
                        if (item.Guid == channelName)
                        {
                            if (groupGuid != "")
                            {
                                item.Equips[equipGuid].Groups[groupGuid].Tags[tagFullName].Name = frmNewTag.TagName;
                                item.Equips[equipGuid].Groups[groupGuid].Tags[tagFullName].Address = frmNewTag.TagAddress;
                                item.Equips[equipGuid].Groups[groupGuid].Tags[tagFullName].Remark = frmNewTag.TagRemark;
                                item.Equips[equipGuid].Groups[groupGuid].Tags[tagFullName].DataType = frmNewTag.TagDataType;
                                item.Equips[equipGuid].Groups[groupGuid].Tags[tagFullName].ReadWrite = frmNewTag.ReadWrite;
                                item.Equips[equipGuid].Groups[groupGuid].Tags[tagFullName].Frequency = frmNewTag.Frequency;
                                item.Equips[equipGuid].Groups[groupGuid].Tags[tagFullName].Zoom = frmNewTag.Zoom;
                            }
                            else
                            {
                                item.Equips[equipGuid].Tags[tagFullName].Name = frmNewTag.TagName;
                                item.Equips[equipGuid].Tags[tagFullName].Address = frmNewTag.TagAddress;
                                item.Equips[equipGuid].Tags[tagFullName].Remark = frmNewTag.TagRemark;
                                item.Equips[equipGuid].Tags[tagFullName].DataType = frmNewTag.TagDataType;
                                item.Equips[equipGuid].Tags[tagFullName].ReadWrite = frmNewTag.ReadWrite;
                                item.Equips[equipGuid].Tags[tagFullName].Frequency = frmNewTag.Frequency;
                                item.Equips[equipGuid].Tags[tagFullName].Zoom = frmNewTag.Zoom;
                            }
                            break;
                        }
                    }
                    DbBussiness.Instance.UpdateTag(frmNewTag.TagGuid, frmNewTag.TagName, tag.FullName, frmNewTag.TagRemark, frmNewTag.TagAddress, frmNewTag.TagDataType.ToString(), frmNewTag.ReadWrite.ToString(), frmNewTag.Frequency, frmNewTag.Zoom);
                    ConnectList.Instance = null;
                    RefreshTags(this.treeView1.SelectedNode);

                }
            }
        }
        #endregion

        #region 编辑设备
        private void toolStripMenuItem4_Click(object sender, EventArgs e)
        {
            BaseClass baseClass = GetNewNode(this.treeView1.SelectedNode);
            if (baseClass is Equip)
            {
                Equip equip = baseClass as Equip;
                FrmNewEquip frmNewEquip = new FrmNewEquip(equip.Name, equip.Ip, equip.Port, equip.Slot, equip.Rack, equip.ChannelType, equip.Type, equip.EquipFullName.Split('.')[0], equip.Guid, equip.EquipFullName.Split('.')[0]);
                if (frmNewEquip.ShowDialog() == DialogResult.OK)
                {
                    Equip equipUpdate = new Equip()
                    {
                        Guid = frmNewEquip.Guid,
                        Ip = frmNewEquip.IP,
                        Port = frmNewEquip.Port,
                        Slot = frmNewEquip.Slot,
                        Rack = frmNewEquip.Rack,
                        Type = frmNewEquip.Type,
                        Name = frmNewEquip.Name,
                        EquipFullName = frmNewEquip.FullName,
                    };




                    EquipChannel equipChannel = null;
                    foreach (var item in EquipChannels.Instance.EquipChannelList)
                    {
                        if (item.Guid == equip.ChannelName)
                        {
                            equipChannel = item;
                            break;
                        }
                    }

                    #region 判断设备是否已存在
                    if (equipChannel != null)
                    {
                        foreach (var item in equipChannel.Equips)
                        {
                            if (frmNewEquip.Name == item.Value.Name && equipUpdate.Guid != item.Value.Guid)
                            {
                                MessageBox.Show("设备已存在");
                                return;
                            }
                        }

                        foreach (var item in equipChannel.Equips)
                        {
                            if (frmNewEquip.Guid == item.Value.Guid)
                            {
                                equipChannel.Equips[item.Key].Ip = equipUpdate.Ip;
                                equipChannel.Equips[item.Key].Port = equipUpdate.Port;
                                equipChannel.Equips[item.Key].Slot = equipUpdate.Slot;
                                equipChannel.Equips[item.Key].Rack = equipUpdate.Rack;
                                equipChannel.Equips[item.Key].Type = equipUpdate.Type;
                                equipChannel.Equips[item.Key].Name = equipUpdate.Name;
                                break;
                            }

                        }
                        DbBussiness.Instance.UpdateEquip(equipUpdate.Ip, equipUpdate.EquipFullName, equipUpdate.Port, equipUpdate.Slot, equipUpdate.Rack, equipUpdate.Type, equipUpdate.Name);
                        ConnectList.Instance = null;
                        this.treeView1.SelectedNode.Text = equipUpdate.Name;
                    }
                    #endregion
                }
            }
        }
        #endregion

        #region 右键选中行
        private void dataGridView1_MouseDown(object sender, MouseEventArgs e)
        {
            int index = GetRowIndexAt(e.Location.Y);
            if (index >= 0)
            {
                this.dataGridView1.ClearSelection();
                this.dataGridView1.Rows[index].Selected = true;
            }
        }
        #endregion

        #region 获取行号
        public int GetRowIndexAt(int mouseLocation_Y)
        {
            if (dataGridView1.FirstDisplayedScrollingRowIndex < 0)
            {
                return -1;  // no rows.   
            }
            if (dataGridView1.ColumnHeadersVisible == true && mouseLocation_Y <= dataGridView1.ColumnHeadersHeight)
            {
                return -1;
            }
            int index = dataGridView1.FirstDisplayedScrollingRowIndex;
            int displayedCount = dataGridView1.DisplayedRowCount(true);
            for (int k = 1; k <= displayedCount;)  // 因为行不能ReOrder，故只需要搜索显示的行   
            {
                if (dataGridView1.Rows[index].Visible == true)
                {
                    Rectangle rect = dataGridView1.GetRowDisplayRectangle(index, true);  // 取该区域的显示部分区域   
                    if (rect.Top <= mouseLocation_Y && mouseLocation_Y < rect.Bottom)
                    {
                        return index;
                    }
                    k++;  // 只计数显示的行;   
                }
                index++;
            }
            return -1;
        }
        #endregion

        #region 系统配置
        private void 系统配置ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FrmConfig frmConfig = new FrmConfig();
            if (frmConfig.ShowDialog() == DialogResult.OK)
            {
                if (app != null)
                {
                    app.StopAsync();
                    app.DisposeAsync();
                }
                Task.Run(() => StartWebApi());
            }
        }
        #endregion

        #region 启动webapi服务
        public void StartWebApi()
        {
            try
            {
                LogClass.Instance.Info($"API服务启动");
                var builder = WebApplication.CreateBuilder();

                // Add services to the container.
                builder.Services.AddControllers();
                // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
                builder.Services.AddEndpointsApiExplorer();
                builder.Services.AddSwaggerGen();

                app = builder.Build();

                // Configure the HTTP request pipeline.
                if (app.Environment.IsDevelopment())
                {
                    app.UseSwagger();
                    app.UseSwaggerUI();
                }

                //app.UseHttpsRedirection();

                app.UseAuthorization();

                app.MapControllers();

                string ip = ConfigDbBussiness.Instance.GetConfigByKey("localhostIP");
                string port = ConfigDbBussiness.Instance.GetConfigByKey("Port", "9099");
                LogClass.Instance.Info($"API服务启动{ip}:{port}");
                app.Run($"http://{ip}:{port}/");

            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"API服务启动失败{ex.Message}");
            }
        }
        #endregion

        #region 导入xml
        /// <summary>
        /// 导入xml，兼容弯弓装备平台
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem3_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "xml文件(*.xml)|*.xml";
            openFileDialog.Multiselect = false;
            openFileDialog.Title = "请选择文件";
            if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string file = openFileDialog.FileName;

                IPC.WinForm.WG.ConfigEquip configEquip = new IPC.WinForm.WG.ConfigEquip();
                Dictionary<string, IPC.WinForm.WG.BaseEquip> keyValuePairs = configEquip.ReadBaseEquip(true, file);

                foreach (IPC.WinForm.WG.ConfigEquip item in keyValuePairs.Values)
                {
                    string guidChannel = Guid.NewGuid().ToString();
                    DbBussiness.Instance.AddChannel(item.Name, item.Main.Brand, guidChannel);
                    string ip = item.IP;
                    string rack = item.Rack;
                    string slot = item.Slot;
                    string port = "";
                    if (item.Main.Brand == "AllenBradley")
                    {
                        port = "44818";
                    }
                    else if (item.Main.Brand == "Siemens")
                    {
                        port = "102";
                    }
                    string guidEquip = Guid.NewGuid().ToString();
                    DbBussiness.Instance.AddEquip(ip, port, slot, rack, item.Main.Model, item.Name, guidChannel + "." + guidEquip, guidChannel, guidEquip, item.Main.Brand);
                    foreach (var itemGroup in item.Group.Values)
                    {
                        foreach (var itemData in itemGroup.Data.Values)
                        {
                            if (itemData.DataType == "")
                            {
                                itemData.DataType = itemGroup.DataType;
                            }
                            itemData.DataType = DeulDataType(itemData.DataType);

                            if (itemData.DataType == "")
                            {
                                continue;
                            }

                            string address = "";
                            if (item.Main.Brand == "Siemens")
                            {
                                if (!itemData.RunName.StartsWith("M") && !itemData.RunName.StartsWith("Q"))
                                {
                                    address = "DB" + itemGroup.Block + "." + itemData.RunName;
                                }
                                else
                                {
                                    address = itemData.RunName;
                                }
                            }
                            else
                            {
                                address = itemData.RunName;
                            }
                            string tagGuid = Guid.NewGuid().ToString();
                            DbBussiness.Instance.AddTag(itemData.Name, address, itemData.DataType, 1000, 1, itemData.Remark, "", "Read", guidChannel + "." + guidEquip + "." + tagGuid, "", guidChannel + "." + guidEquip, tagGuid);
                        }
                    }
                }
            }
            this.richTextBox1.AppendText($"xml导入成功");
        }


        #region 处理数据类型
        private string DeulDataType(string dataType)
        {
            try
            {
                string dataType2 = dataType.ToLower();
                if (dataType2.Contains("uint16"))
                    return "UInt16";
                if (dataType2.Contains("uint32"))
                    return "UInt32";
                if (dataType2.Contains("uint64"))
                    return "UInt64";
                if (dataType2.Contains("single"))
                    return "Float";
                else if (dataType2.Contains("int16"))
                {
                    return "Int16";
                }
                if (dataType2.Contains("int32"))
                    return "Int32";
                if (dataType2.Contains("int64"))
                    return "Int64";
                if (dataType2.Contains("double"))
                    return "Double";
                if (dataType2.Contains("bool"))
                    return "Bool";
                if (dataType2.Contains("string"))
                    return "String";
                if (dataType2.Contains("byte"))
                    return "Byte";
                return dataType;
            }
            catch (Exception ex)
            {
                return "";
            }
        }
        #endregion
        #endregion

        #region 调用livechart2查询走势图
        private void 趋势图ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.dataGridView1.SelectedRows.Count <= 0)
                {
                    return;
                }

                Dictionary<string, List<BsonDocument>> dic = new Dictionary<string, List<BsonDocument>>();
                foreach (DataGridViewRow item in this.dataGridView1.SelectedRows)
                {
                    string fullName = item.Cells["FullName"].Value.ToString();
                    string beginTime = DateTime.Now.AddHours(-1).ToString();
                    string endTime = DateTime.Now.ToString();
                    var list = MongoDB.MongoOperate.Instance.Select(fullName, beginTime, endTime);
                    if (!dic.ContainsKey(fullName))
                    {
                        dic.Add(fullName, list);
                    }
                }
                ViewModel.ViewModel viewModel = new ViewModel.ViewModel(dic);
                FrmSerial frmSerial = new FrmSerial(viewModel);
                frmSerial.Show();
            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"加载趋势图错误{ex.Message}");
            }
        }
        #endregion

        #region 调用livechart2观测仪表
        private void 仪表图ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.dataGridView1.SelectedRows.Count <= 0)
                {
                    return;
                }

                Dictionary<string, List<BsonDocument>> dic = new Dictionary<string, List<BsonDocument>>();

                string? fullName = this.dataGridView1.SelectedRows[0].Cells["FullName"].Value.ToString();
                string? remark = this.dataGridView1.SelectedRows[0].Cells["Remark"].Value.ToString();
                var list = MongoDB.MongoOperate.Instance.Select(fullName);
                double value = 0;
                if (list.Count > 0)
                {
                    value = list[0].GetValue("Value").ToString().ToDouble(0);
                }
                AngularViewModel angularViewModel = new AngularViewModel(remark);
                angularViewModel.UpdateValue(value);

                FrmAngular frmAngular = new FrmAngular(remark, angularViewModel);
                frmAngular.Show();
            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"加仪表图错误{ex.Message}");
            }
        } 
        #endregion
    }
}
